#include "stdafx.h"
#include "./impactmgr.h"

ImpactMgr::ImpactObjList ImpactMgr::m_list;

ImpactMgr::ImpactMgr()
{
	::InitializeCriticalSection(&m_csThreadSafe);
}

ImpactMgr::~ImpactMgr()
{

}

void ImpactMgr::RegisterImpactObj(ImpactObj* p)
{
	::EnterCriticalSection(&m_csThreadSafe);
	m_list.push_back(p);
	::LeaveCriticalSection(&m_csThreadSafe);
}

void ImpactMgr::UnRegisterImpactObj(ImpactObj* p)
{
	::EnterCriticalSection(&m_csThreadSafe);
	ImpactObjIter iter = find(m_list.begin(), m_list.end(), p);
	if (iter != m_list.end())
	{
		m_list.erase(iter);
	}
	::LeaveCriticalSection(&m_csThreadSafe);
}

ImpactObj* ImpactMgr::CalcImpact(Point& newPos, ImpactObj* pCalcObj, ImpactObj* pAddtionFlitObj)
{
	::EnterCriticalSection(&m_csThreadSafe);
	ImpactObjIter iter;
	for (iter = m_list.begin(); iter != m_list.end(); ++iter)
	{
		ImpactObj* pObj = *iter;
		if (pObj != pCalcObj && pObj != pAddtionFlitObj)
		{
			Point pos1 = pCalcObj->GetPos();
			Point pos2 = pObj->GetPos();

			float minlength = pCalcObj->GetRange() + pObj->GetRange();
			if (CheckIntersection(pos1, pos2, minlength))
			{
				float radian = pCalcObj->GetHeadingRadian();

				float rtan = tanf(radian);
				float rsin = sinf(radian);
				float rcos = cosf(radian);

				float xl = (pos2.x + pos1.x * rtan * rtan - pos1.y * rtan + pos2.y * rtan) / (1 + rtan * rtan);
				float yl = xl * rtan - pos1.x * rtan + pos1.y;

				float d = sqrtf(minlength * minlength - (xl - pos2.x) * (xl - pos2.x) - (yl - pos2.y) * (yl - pos2.y));

				newPos.x = xl - d * rcos;
				newPos.y = yl - d * rsin;

				::LeaveCriticalSection(&m_csThreadSafe);
				return pObj;
			}
		}
	}

	::LeaveCriticalSection(&m_csThreadSafe);
	return NULL;
}

ImpactObj* ImpactMgr::CalcIntersection(ImpactObj* pCalcObj, ImpactObj* pAddtionFlitObj)
{
	::EnterCriticalSection(&m_csThreadSafe);
	ImpactObjIter iter;
	for (iter = m_list.begin(); iter != m_list.end(); ++iter)
	{
		ImpactObj* pObj = *iter;
		if (pObj != pCalcObj && pObj != pAddtionFlitObj)
		{
			Point pos1 = pCalcObj->GetPos();
			Point pos2 = pObj->GetPos();

			float minlength = pCalcObj->GetRange() + pObj->GetRange();
			if (CheckIntersection(pos1, pos2, minlength))
			{
				::LeaveCriticalSection(&m_csThreadSafe);
				return pObj;
			}
		}
	}

	::LeaveCriticalSection(&m_csThreadSafe);
	return NULL;
}

bool ImpactMgr::CheckIntersection(Point pos1, Point pos2, float minlength)
{
	return (MathUtils::Square(pos1.x - pos2.x) + MathUtils::Square(pos1.y - pos2.y)) < MathUtils::Square(minlength);
}